home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / r_surf.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  15KB  |  679 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_surf.c: surface-related refresh code
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. drawsurf_t    r_drawsurf;
  26.  
  27. int                lightleft, sourcesstep, blocksize, sourcetstep;
  28. int                lightdelta, lightdeltastep;
  29. int                lightright, lightleftstep, lightrightstep, blockdivshift;
  30. unsigned        blockdivmask;
  31. void            *prowdestbase;
  32. unsigned char    *pbasesource;
  33. int                surfrowbytes;    // used by ASM files
  34. unsigned        *r_lightptr;
  35. int                r_stepback;
  36. int                r_lightwidth;
  37. int                r_numhblocks, r_numvblocks;
  38. unsigned char    *r_source, *r_sourcemax;
  39.  
  40. void R_DrawSurfaceBlock8_mip0 (void);
  41. void R_DrawSurfaceBlock8_mip1 (void);
  42. void R_DrawSurfaceBlock8_mip2 (void);
  43. void R_DrawSurfaceBlock8_mip3 (void);
  44.  
  45. static void    (*surfmiptable[4])(void) = {
  46.     R_DrawSurfaceBlock8_mip0,
  47.     R_DrawSurfaceBlock8_mip1,
  48.     R_DrawSurfaceBlock8_mip2,
  49.     R_DrawSurfaceBlock8_mip3
  50. };
  51.  
  52.  
  53.  
  54. unsigned        blocklights[18*18];
  55.  
  56. /*
  57. ===============
  58. R_AddDynamicLights
  59. ===============
  60. */
  61. void R_AddDynamicLights (void)
  62. {
  63.     msurface_t *surf;
  64.     int            lnum;
  65.     int            sd, td;
  66.     float        dist, rad, minlight;
  67.     vec3_t        impact, local;
  68.     int            s, t;
  69.     int            i;
  70.     int            smax, tmax;
  71.     mtexinfo_t    *tex;
  72.  
  73.     surf = r_drawsurf.surf;
  74.     smax = (surf->extents[0]>>4)+1;
  75.     tmax = (surf->extents[1]>>4)+1;
  76.     tex = surf->texinfo;
  77.  
  78.     for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
  79.     {
  80.         if ( !(surf->dlightbits & (1<<lnum) ) )
  81.             continue;        // not lit by this light
  82.  
  83.         rad = cl_dlights[lnum].radius;
  84.         dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
  85.                 surf->plane->dist;
  86.         rad -= fabs(dist);
  87.         minlight = cl_dlights[lnum].minlight;
  88.         if (rad < minlight)
  89.             continue;
  90.         minlight = rad - minlight;
  91.  
  92.         for (i=0 ; i<3 ; i++)
  93.         {
  94.             impact[i] = cl_dlights[lnum].origin[i] -
  95.                     surf->plane->normal[i]*dist;
  96.         }
  97.  
  98.         local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
  99.         local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
  100.  
  101.         local[0] -= surf->texturemins[0];
  102.         local[1] -= surf->texturemins[1];
  103.         
  104.         for (t = 0 ; t<tmax ; t++)
  105.         {
  106.             td = local[1] - t*16;
  107.             if (td < 0)
  108.                 td = -td;
  109.             for (s=0 ; s<smax ; s++)
  110.             {
  111.                 sd = local[0] - s*16;
  112.                 if (sd < 0)
  113.                     sd = -sd;
  114.                 if (sd > td)
  115.                     dist = sd + (td>>1);
  116.                 else
  117.                     dist = td + (sd>>1);
  118.                 if (dist < minlight)
  119. #ifdef QUAKE2
  120.                 {
  121.                     unsigned temp;
  122.                     temp = (rad - dist)*256;
  123.                     i = t*smax + s;
  124.                     if (!cl_dlights[lnum].dark)
  125.                         blocklights[i] += temp;
  126.                     else
  127.                     {
  128.                         if (blocklights[i] > temp)
  129.                             blocklights[i] -= temp;
  130.                         else
  131.                             blocklights[i] = 0;
  132.                     }
  133.                 }
  134. #else
  135.                     blocklights[t*smax + s] += (rad - dist)*256;
  136. #endif
  137.             }
  138.         }
  139.     }
  140. }
  141.  
  142. /*
  143. ===============
  144. R_BuildLightMap
  145.  
  146. Combine and scale multiple lightmaps into the 8.8 format in blocklights
  147. ===============
  148. */
  149. void R_BuildLightMap (void)
  150. {
  151.     int            smax, tmax;
  152.     int            t;
  153.     int            i, size;
  154.     byte        *lightmap;
  155.     unsigned    scale;
  156.     int            maps;
  157.     msurface_t    *surf;
  158.  
  159.     surf = r_drawsurf.surf;
  160.  
  161.     smax = (surf->extents[0]>>4)+1;
  162.     tmax = (surf->extents[1]>>4)+1;
  163.     size = smax*tmax;
  164.     lightmap = surf->samples;
  165.  
  166.     if (r_fullbright.value || !cl.worldmodel->lightdata)
  167.     {
  168.         for (i=0 ; i<size ; i++)
  169.             blocklights[i] = 0;
  170.         return;
  171.     }
  172.  
  173. // clear to ambient
  174.     for (i=0 ; i<size ; i++)
  175.         blocklights[i] = r_refdef.ambientlight<<8;
  176.  
  177.  
  178. // add all the lightmaps
  179.     if (lightmap)
  180.         for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  181.              maps++)
  182.         {
  183.             scale = r_drawsurf.lightadj[maps];    // 8.8 fraction        
  184.             for (i=0 ; i<size ; i++)
  185.                 blocklights[i] += lightmap[i] * scale;
  186.             lightmap += size;    // skip to next lightmap
  187.         }
  188.  
  189. // add all the dynamic lights
  190.     if (surf->dlightframe == r_framecount)
  191.         R_AddDynamicLights ();
  192.  
  193. // bound, invert, and shift
  194.     for (i=0 ; i<size ; i++)
  195.     {
  196.         t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
  197.  
  198.         if (t < (1 << 6))
  199.             t = (1 << 6);
  200.  
  201.         blocklights[i] = t;
  202.     }
  203. }
  204.  
  205.  
  206. /*
  207. ===============
  208. R_TextureAnimation
  209.  
  210. Returns the proper texture for a given time and base texture
  211. ===============
  212. */
  213. texture_t *R_TextureAnimation (texture_t *base)
  214. {
  215.     int        reletive;
  216.     int        count;
  217.  
  218.     if (currententity->frame)
  219.     {
  220.         if (base->alternate_anims)
  221.             base = base->alternate_anims;
  222.     }
  223.     
  224.     if (!base->anim_total)
  225.         return base;
  226.  
  227.     reletive = (int)(cl.time*10) % base->anim_total;
  228.  
  229.     count = 0;    
  230.     while (base->anim_min > reletive || base->anim_max <= reletive)
  231.     {
  232.         base = base->anim_next;
  233.         if (!base)
  234.             Sys_Error ("R_TextureAnimation: broken cycle");
  235.         if (++count > 100)
  236.             Sys_Error ("R_TextureAnimation: infinite cycle");
  237.     }
  238.  
  239.     return base;
  240. }
  241.  
  242.  
  243. /*
  244. ===============
  245. R_DrawSurface
  246. ===============
  247. */
  248. void R_DrawSurface (void)
  249. {
  250.     unsigned char    *basetptr;
  251.     int                smax, tmax, twidth;
  252.     int                u;
  253.     int                soffset, basetoffset, texwidth;
  254.     int                horzblockstep;
  255.     unsigned char    *pcolumndest;
  256.     void            (*pblockdrawer)(void);
  257.     texture_t        *mt;
  258.  
  259. // calculate the lightings
  260.     R_BuildLightMap ();
  261.     
  262.     surfrowbytes = r_drawsurf.rowbytes;
  263.  
  264.     mt = r_drawsurf.texture;
  265.     
  266.     r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
  267.     
  268. // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
  269. // from a source range of 0 - 255
  270.     
  271.     texwidth = mt->width >> r_drawsurf.surfmip;
  272.  
  273.     blocksize = 16 >> r_drawsurf.surfmip;
  274.     blockdivshift = 4 - r_drawsurf.surfmip;
  275.     blockdivmask = (1 << blockdivshift) - 1;
  276.     
  277.     r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
  278.  
  279.     r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
  280.     r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
  281.  
  282. //==============================
  283.  
  284.     if (r_pixbytes == 1)
  285.     {
  286.         pblockdrawer = surfmiptable[r_drawsurf.surfmip];
  287.     // TODO: only needs to be set when there is a display settings change
  288.         horzblockstep = blocksize;
  289.     }
  290.     else
  291.     {
  292.         pblockdrawer = R_DrawSurfaceBlock16;
  293.     // TODO: only needs to be set when there is a display settings change
  294.         horzblockstep = blocksize << 1;
  295.     }
  296.  
  297.     smax = mt->width >> r_drawsurf.surfmip;
  298.     twidth = texwidth;
  299.     tmax = mt->height >> r_drawsurf.surfmip;
  300.     sourcetstep = texwidth;
  301.     r_stepback = tmax * twidth;
  302.  
  303.     r_sourcemax = r_source + (tmax * smax);
  304.  
  305.     soffset = r_drawsurf.surf->texturemins[0];
  306.     basetoffset = r_drawsurf.surf->texturemins[1];
  307.  
  308. // << 16 components are to guarantee positive values for %
  309.     soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
  310.     basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) 
  311.         + (tmax << 16)) % tmax) * twidth)];
  312.  
  313.     pcolumndest = r_drawsurf.surfdat;
  314.  
  315.     for (u=0 ; u<r_numhblocks; u++)
  316.     {
  317.         r_lightptr = blocklights + u;
  318.  
  319.         prowdestbase = pcolumndest;
  320.  
  321.         pbasesource = basetptr + soffset;
  322.  
  323.         (*pblockdrawer)();
  324.  
  325.         soffset = soffset + blocksize;
  326.         if (soffset >= smax)
  327.             soffset = 0;
  328.  
  329.         pcolumndest += horzblockstep;
  330.     }
  331. }
  332.  
  333.  
  334. //=============================================================================
  335.  
  336. #if    !id386
  337.  
  338. /*
  339. ================
  340. R_DrawSurfaceBlock8_mip0
  341. ================
  342. */
  343. void R_DrawSurfaceBlock8_mip0 (void)
  344. {
  345.     int                v, i, b, lightstep, lighttemp, light;
  346.     unsigned char    pix, *psource, *prowdest;
  347.  
  348.     psource = pbasesource;
  349.     prowdest = prowdestbase;
  350.  
  351.     for (v=0 ; v<r_numvblocks ; v++)
  352.     {
  353.     // FIXME: make these locals?
  354.     // FIXME: use delta rather than both right and left, like ASM?
  355.         lightleft = r_lightptr[0];
  356.         lightright = r_lightptr[1];
  357.         r_lightptr += r_lightwidth;
  358.         lightleftstep = (r_lightptr[0] - lightleft) >> 4;
  359.         lightrightstep = (r_lightptr[1] - lightright) >> 4;
  360.  
  361.         for (i=0 ; i<16 ; i++)
  362.         {
  363.             lighttemp = lightleft - lightright;
  364.             lightstep = lighttemp >> 4;
  365.  
  366.             light = lightright;
  367.  
  368.             for (b=15; b>=0; b--)
  369.             {
  370.                 pix = psource[b];
  371.                 prowdest[b] = ((unsigned char *)vid.colormap)
  372.                         [(light & 0xFF00) + pix];
  373.                 light += lightstep;
  374.             }
  375.     
  376.             psource += sourcetstep;
  377.             lightright += lightrightstep;
  378.             lightleft += lightleftstep;
  379.             prowdest += surfrowbytes;
  380.         }
  381.  
  382.         if (psource >= r_sourcemax)
  383.             psource -= r_stepback;
  384.     }
  385. }
  386.  
  387.  
  388. /*
  389. ================
  390. R_DrawSurfaceBlock8_mip1
  391. ================
  392. */
  393. void R_DrawSurfaceBlock8_mip1 (void)
  394. {
  395.     int                v, i, b, lightstep, lighttemp, light;
  396.     unsigned char    pix, *psource, *prowdest;
  397.  
  398.     psource = pbasesource;
  399.     prowdest = prowdestbase;
  400.  
  401.     for (v=0 ; v<r_numvblocks ; v++)
  402.     {
  403.     // FIXME: make these locals?
  404.     // FIXME: use delta rather than both right and left, like ASM?
  405.         lightleft = r_lightptr[0];
  406.         lightright = r_lightptr[1];
  407.         r_lightptr += r_lightwidth;
  408.         lightleftstep = (r_lightptr[0] - lightleft) >> 3;
  409.         lightrightstep = (r_lightptr[1] - lightright) >> 3;
  410.  
  411.         for (i=0 ; i<8 ; i++)
  412.         {
  413.             lighttemp = lightleft - lightright;
  414.             lightstep = lighttemp >> 3;
  415.  
  416.             light = lightright;
  417.  
  418.             for (b=7; b>=0; b--)
  419.             {
  420.                 pix = psource[b];
  421.                 prowdest[b] = ((unsigned char *)vid.colormap)
  422.                         [(light & 0xFF00) + pix];
  423.                 light += lightstep;
  424.             }
  425.     
  426.             psource += sourcetstep;
  427.             lightright += lightrightstep;
  428.             lightleft += lightleftstep;
  429.             prowdest += surfrowbytes;
  430.         }
  431.  
  432.         if (psource >= r_sourcemax)
  433.             psource -= r_stepback;
  434.     }
  435. }
  436.  
  437.  
  438. /*
  439. ================
  440. R_DrawSurfaceBlock8_mip2
  441. ================
  442. */
  443. void R_DrawSurfaceBlock8_mip2 (void)
  444. {
  445.     int                v, i, b, lightstep, lighttemp, light;
  446.     unsigned char    pix, *psource, *prowdest;
  447.  
  448.     psource = pbasesource;
  449.     prowdest = prowdestbase;
  450.  
  451.     for (v=0 ; v<r_numvblocks ; v++)
  452.     {
  453.     // FIXME: make these locals?
  454.     // FIXME: use delta rather than both right and left, like ASM?
  455.         lightleft = r_lightptr[0];
  456.         lightright = r_lightptr[1];
  457.         r_lightptr += r_lightwidth;
  458.         lightleftstep = (r_lightptr[0] - lightleft) >> 2;
  459.         lightrightstep = (r_lightptr[1] - lightright) >> 2;
  460.  
  461.         for (i=0 ; i<4 ; i++)
  462.         {
  463.             lighttemp = lightleft - lightright;
  464.             lightstep = lighttemp >> 2;
  465.  
  466.             light = lightright;
  467.  
  468.             for (b=3; b>=0; b--)
  469.             {
  470.                 pix = psource[b];
  471.                 prowdest[b] = ((unsigned char *)vid.colormap)
  472.                         [(light & 0xFF00) + pix];
  473.                 light += lightstep;
  474.             }
  475.     
  476.             psource += sourcetstep;
  477.             lightright += lightrightstep;
  478.             lightleft += lightleftstep;
  479.             prowdest += surfrowbytes;
  480.         }
  481.  
  482.         if (psource >= r_sourcemax)
  483.             psource -= r_stepback;
  484.     }
  485. }
  486.  
  487.  
  488. /*
  489. ================
  490. R_DrawSurfaceBlock8_mip3
  491. ================
  492. */
  493. void R_DrawSurfaceBlock8_mip3 (void)
  494. {
  495.     int                v, i, b, lightstep, lighttemp, light;
  496.     unsigned char    pix, *psource, *prowdest;
  497.  
  498.     psource = pbasesource;
  499.     prowdest = prowdestbase;
  500.  
  501.     for (v=0 ; v<r_numvblocks ; v++)
  502.     {
  503.     // FIXME: make these locals?
  504.     // FIXME: use delta rather than both right and left, like ASM?
  505.         lightleft = r_lightptr[0];
  506.         lightright = r_lightptr[1];
  507.         r_lightptr += r_lightwidth;
  508.         lightleftstep = (r_lightptr[0] - lightleft) >> 1;
  509.         lightrightstep = (r_lightptr[1] - lightright) >> 1;
  510.  
  511.         for (i=0 ; i<2 ; i++)
  512.         {
  513.             lighttemp = lightleft - lightright;
  514.             lightstep = lighttemp >> 1;
  515.  
  516.             light = lightright;
  517.  
  518.             for (b=1; b>=0; b--)
  519.             {
  520.                 pix = psource[b];
  521.                 prowdest[b] = ((unsigned char *)vid.colormap)
  522.                         [(light & 0xFF00) + pix];
  523.                 light += lightstep;
  524.             }
  525.     
  526.             psource += sourcetstep;
  527.             lightright += lightrightstep;
  528.             lightleft += lightleftstep;
  529.             prowdest += surfrowbytes;
  530.         }
  531.  
  532.         if (psource >= r_sourcemax)
  533.             psource -= r_stepback;
  534.     }
  535. }
  536.  
  537.  
  538. /*
  539. ================
  540. R_DrawSurfaceBlock16
  541.  
  542. FIXME: make this work
  543. ================
  544. */
  545. void R_DrawSurfaceBlock16 (void)
  546. {
  547.     int                k;
  548.     unsigned char    *psource;
  549.     int                lighttemp, lightstep, light;
  550.     unsigned short    *prowdest;
  551.  
  552.     prowdest = (unsigned short *)prowdestbase;
  553.  
  554.     for (k=0 ; k<blocksize ; k++)
  555.     {
  556.         unsigned short    *pdest;
  557.         unsigned char    pix;
  558.         int                b;
  559.  
  560.         psource = pbasesource;
  561.         lighttemp = lightright - lightleft;
  562.         lightstep = lighttemp >> blockdivshift;
  563.  
  564.         light = lightleft;
  565.         pdest = prowdest;
  566.  
  567.         for (b=0; b<blocksize; b++)
  568.         {
  569.             pix = *psource;
  570.             *pdest = vid.colormap16[(light & 0xFF00) + pix];
  571.             psource += sourcesstep;
  572.             pdest++;
  573.             light += lightstep;
  574.         }
  575.  
  576.         pbasesource += sourcetstep;
  577.         lightright += lightrightstep;
  578.         lightleft += lightleftstep;
  579.         prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
  580.     }
  581.  
  582.     prowdestbase = prowdest;
  583. }
  584.  
  585. #endif
  586.  
  587.  
  588. //============================================================================
  589.  
  590. /*
  591. ================
  592. R_GenTurbTile
  593. ================
  594. */
  595. void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
  596. {
  597.     int        *turb;
  598.     int        i, j, s, t;
  599.     byte    *pd;
  600.     
  601.     turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  602.     pd = (byte *)pdest;
  603.  
  604.     for (i=0 ; i<TILE_SIZE ; i++)
  605.     {
  606.         for (j=0 ; j<TILE_SIZE ; j++)
  607.         {    
  608.             s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
  609.             t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
  610.             *pd++ = *(pbasetex + (t<<6) + s);
  611.         }
  612.     }
  613. }
  614.  
  615.  
  616. /*
  617. ================
  618. R_GenTurbTile16
  619. ================
  620. */
  621. void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
  622. {
  623.     int                *turb;
  624.     int                i, j, s, t;
  625.     unsigned short    *pd;
  626.  
  627.     turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  628.     pd = (unsigned short *)pdest;
  629.  
  630.     for (i=0 ; i<TILE_SIZE ; i++)
  631.     {
  632.         for (j=0 ; j<TILE_SIZE ; j++)
  633.         {    
  634.             s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
  635.             t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
  636.             *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
  637.         }
  638.     }
  639. }
  640.  
  641.  
  642. /*
  643. ================
  644. R_GenTile
  645. ================
  646. */
  647. void R_GenTile (msurface_t *psurf, void *pdest)
  648. {
  649.     if (psurf->flags & SURF_DRAWTURB)
  650.     {
  651.         if (r_pixbytes == 1)
  652.         {
  653.             R_GenTurbTile ((pixel_t *)
  654.                 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  655.         }
  656.         else
  657.         {
  658.             R_GenTurbTile16 ((pixel_t *)
  659.                 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  660.         }
  661.     }
  662.     else if (psurf->flags & SURF_DRAWSKY)
  663.     {
  664.         if (r_pixbytes == 1)
  665.         {
  666.             R_GenSkyTile (pdest);
  667.         }
  668.         else
  669.         {
  670.             R_GenSkyTile16 (pdest);
  671.         }
  672.     }
  673.     else
  674.     {
  675.         Sys_Error ("Unknown tile type");
  676.     }
  677. }
  678.  
  679.